Repository navigation
fix(gateway): honor all inference protection modes - #2457
Conversation
hidb4ai
left a comment
There was a problem hiding this comment.
Reviewed 6bbe031. No blocking issues found. The mode-specific admission behavior is consistent with the documented contract, while authorization, exact prepared-content checks, expiry, and request/response bindings remain enforced.
No database tables or new public operations are introduced; the existing context-check response gains a coverage enum value. Local runtime, authorization, contract, and real Core/Gateway process checks passed. Required CI is still in progress.
hidb4ai
left a comment
There was a problem hiding this comment.
Reviewed 6bbe031. No blocking findings. Non-enforcing admission retains context authorization and request/response binding checks, with a distinct coverage profile. No new database tables or public operations; the existing response enum is extended and documented.
Validated the base/head behavior, contracts, and real local Core/Gateway processes. Process tests passed after a startup-timeout retry using a larger startup allowance on this host. Remaining CI checks must pass before merge.
|
please resolve conflict |
42dfb56 to
a676623
Compare
| Windows/macOS execution, native credential persistence, installed UI or release readiness. | ||
| Historical qualification records retain their identities and evidence. | ||
|
|
||
| ## Managed observability protocol qualification |
There was a problem hiding this comment.
[P3] Restore the historical qualification sections
Deleting these four sections leaves four historical records in desktop/src-tauri/src/connections/compatibility.json with evidence links pointing to nonexistent anchors, removing access to their documented qualification scope. Restore the sections, or preserve the evidence elsewhere and update the catalog links.
There was a problem hiding this comment.
补充精确范围与同源副作用,供按同一处修复。
被删章节 ↔ 悬空记录的准确对应(本 head a676623b,desktop/VALIDATION.md 对 origin/master@69b2d7e2)
按标题生成锚点做集合差,本 PR 删掉 4 个锚点,正好对应 4 条仍在 compatibility.json 里的记录(evidence 字段仍指向这些锚点):
| 被删锚点 | 悬空记录 | 该记录 contractSha256 |
|---|---|---|
managed-observability-protocol-qualification |
sqlite-observability-9f279e4e-v1 |
44194cfe8ab1… |
managed-observability-with-inference-privacy |
sqlite-observability-a9f6fd36-v1 |
ad6c1e769089… |
server-4568b499-protocol-qualification |
sqlite-observability-4568b499-v1 |
de74d8063439… |
server-da44b918-protocol-qualification |
sqlite-observability-da44b918-v1 |
4d8334f58b97… |
要点是第三条:sqlite-observability-4568b499-v1 的摘要 de74d806… 就是 master 当前的 bundled 契约摘要(origin/master:desktop/src-tauri/src/transport/operations.json),也就是说被删掉的不只是历史档案,还包含 master 现役记录的唯一证据段。
同源副作用:整份文件取自旧副本,不只是删章节
- master 侧
desktop/VALIDATION.md有 3 处e4d5e873…/581cf26b…(clean Desktop 提交与 disposable fixture 提交),本 head 归零; - 同时删掉了「native suite 133 tests / 183 frontend / 62 API-Desktop contract」等实测计数,替换为无数字的概述;
- head 提交历史是
57d79337 chore: merge master into gateway protection modes与a676623b merge: sync ... with master两个 merge,符合「冲突按 ours 整文件解」的特征,与该 merge 正向新增的Server 56683483/Server 57d79337两节并存。
定级:我按 §4 仍定 P2 而非 P1——证据可从 git 历史恢复,没有 CI 门禁覆盖锚点(tests/test_desktop_contract.py 只校验 contractSha256 与 operation 集合,不校验 evidence 锚点),因此不构成阻断。修复应是恢复这四段(而不是改成指向别处的指针),并保留 master 已记录的 probe 提交与计数。
There was a problem hiding this comment.
Addressed in 0caff3c. The branch now contains the minimal Gateway mode change on master ee3c1ee. desktop/VALIDATION.md and the compatibility catalog are identical to that master commit, so this PR no longer deletes the historical qualification sections or replaces their probe identities and test evidence. This also addresses the additional deletion details in the follow-up comment.
| [compatibility.json](src-tauri/src/connections/compatibility.json) preserves each recorded Server source, normalized OpenAPI contract digest, qualification-wheel digest and operation set. Historical records retain their exact identities and evidence. A record qualifies only its recorded Server source, wheel and contract; records with a different contract digest are disabled in the selector. Saved unavailable selections remain visible until explicitly replaced. Selecting a profile does not extend its recorded operation set or qualify a different Server source. CI builds have their own artifact identities and do not change product qualification. | ||
|
|
||
| Statistics additionally require `get_stats` in the selected record's independently qualified operation set. | ||
| The observability qualification records are retained alongside the inference-protection records. `sqlite-observability-stats-4568b499-v1` matches the current bundled API contract and independently qualifies all twelve operations, including `get_stats`; `sqlite-observability-4568b499-v1` retains its eleven-operation evidence. Statistics require `get_stats` in the selected record's independently qualified operation set. |
There was a problem hiding this comment.
[P2] 本行「匹配当前 bundled 契约」的断言与本 PR 的摘要前移冲突,照做会选到被选择器禁用的记录
sqlite-observability-stats-4568b499-v1 的 contractSha256 在本 head 仍是 de74d8063439…,而本 PR 改了 openapi/powercontext.yaml(新增 coverage.profile 的 context-bindings.v1 枚举与两处 description),desktop/src-tauri/src/transport/operations.json 的 bundled 摘要已前移到 3ff44a9c7cb0…。复算一致:sha256(LF(openapi/powercontext.yaml@a676623b)) == 3ff44a9c7cb016f4… == operations.json:contractSha256;compatibility.json 54 条记录里与 3ff44a9c… 相等的只有 sqlite-stats-57d79337-merged-v1,sqlite-observability-stats-4568b499-v1 与 bundled 摘要不再相等。
影响:同段第 180 行刚写明「Records with a different contract digest are disabled in the selector」,并要求「explicitly selecting the record whose tested Server source and wheel match the deployment」。按本行文字去选 sqlite-observability-stats-4568b499-v1 的部署方,在选择器里看到的是一条被禁用记录;同一段第 180 行又说 sqlite-stats-57d79337-merged-v1 才「under the current contract digest」,两句话在本 head 相互矛盾。
建议:把本行改为「sqlite-observability-stats-4568b499-v1 保留其在 de74d806… 下的十二操作资格;当前 bundled 摘要由 sqlite-stats-57d79337-merged-v1 承载」,或重新实测后补齐对应记录。若要防同类复发,可对这句加一条断言(operations.json["contractSha256"] 必须等于本段点名的记录),否则下次契约文本再改时同一句会再次失效。
There was a problem hiding this comment.
Addressed in 0caff3c by removing the OpenAPI/coverage-profile extension and all Desktop changes from this PR. The OpenAPI contract, generated Desktop operations, compatibility catalog, and VALIDATION.md are identical to master ee3c1ee. This PR therefore no longer advances the bundled contract digest or introduces the contradictory current-contract qualification claim. The remaining change is limited to Gateway admission under the four existing privacy modes.
knqiufan
left a comment
There was a problem hiding this comment.
The existing historical-evidence and current-contract qualification findings remain open. The newly added merged qualification also needs its evidence identity corrected.
| "evidence": "desktop/VALIDATION.md#server-57d79337-statistics-product-qualification" | ||
| }, | ||
| { | ||
| "id": "sqlite-stats-57d79337-merged-v1", |
There was a problem hiding this comment.
[P2] Qualify the Server artifact against the recorded contract
This entry pairs Server commit 57d79337 and its original wheel with contract digest 3ff44a9c…, but that commit's OpenAPI digest is d8cf5d80…. The linked validation describes the original qualification; no separate evidence was found for this merged contract. As written the record makes a qualification claim that the recorded artifact and contract identity do not substantiate. Use a matching built artifact and actual qualification, preserving the historical record.
There was a problem hiding this comment.
Addressed in 0caff3c. The unsupported sqlite-stats-57d79337-merged-v1 qualification added by this PR has been removed along with the other Desktop changes. The compatibility catalog and validation evidence now match master ee3c1ee exactly; this PR makes no new Server artifact or Desktop qualification claim and does not change the OpenAPI contract.
There was a problem hiding this comment.
@knqiufan The PR now contains only the Gateway mode handling and its tests/documentation, rebased onto master 7fef43d as b6ad802. Desktop, its qualification catalog/evidence, OpenAPI and generated models are unchanged from master. The mismatched qualification record from the reviewed a676623 was removed. Could you re-review the current head and update the changes-requested verdict if this addresses your concern? CI is rerunning with the merged #2552 scoring-test fix.
a676623 to
0caff3c
Compare
hireview001
left a comment
There was a problem hiding this comment.
- CI failed: CI result (failure).
- CI failed: Upgrade release gate (failure).
- CI failed: tests (3.12, e2e) (failure).
- CI failed: Main (failure). Failed steps: tests (3.12, e2e) / Run remaining end-to-end tests; Upgrade release gate / Require the selected parallel acceptance workflow; CI result / Require successful selected checks.
| else policy.decision(request.phase, "allow", complete=True) | ||
| ) | ||
| if assessed.decision != "allow" or not assessed.coverage.complete: | ||
| if policy.enforcing and (assessed.decision != "allow" or not assessed.coverage.complete): |
There was a problem hiding this comment.
[P2] Handle invalid carriers independently of enforcement mode
With a configured target, malformed or duplicate-key JSON now reaches _validate_prepared() in disabled, shadow, and advisory modes, where uncaught parser exceptions produce HTTP 500. Validate carriers independently of privacy enforcement and translate parsing failures into a controlled invalid-carrier response.
There was a problem hiding this comment.
Fixed in 428172c. Request carrier parsing now translates ValueError/RecursionError at the parse_model_json boundary into InvalidRuntimeRequestError without exposing input content. HTTP regressions cover malformed JSON, duplicate keys, and non-object roots in disabled, shadow, and advisory modes; each returns 422 invalid_request rather than an uncaught server error.
| decision="allow", | ||
| coverage=assessed.coverage, | ||
| reason_codes=assessed.reason_codes, | ||
| coverage=assessed.coverage if policy.enforcing else PrivacyCoverage(complete=True), |
There was a problem hiding this comment.
[P2] Distinguish non-enforcing admission from complete privacy coverage
Non-enforcing modes now report complete text-and-tools.v1 coverage for uninspected responses, violating RFC #2086's explicit requirement that disabled or observation-only paths not advertise enforcing coverage. Existing consumers such as external_executor._require_allow() consequently accept those responses as fully checked; distinguish non-enforcing admission explicitly while preserving truthful coverage.
There was a problem hiding this comment.
Rewritten in 428172c. Core now reports coverage.complete=false for every non-enforcing admission, including uninspected responses. Gateway remains strict by default and accepts incomplete coverage only after its existing trusted Core capability discovery explicitly reports enforcing=false. This applies to send, retry, and release while retaining schema, phase, binding, deadline, and block/withhold checks. The Python SDK/external executor remain strict; an HTTP-to-executor regression proves allow+false produces zero upstream sends. No new coverage profile, API fields, OpenAPI changes, or Desktop changes are included.
0caff3c to
428172c
Compare
428172c to
b6ad802
Compare
Which issue or RFC does this PR close?
Related to #2311. Enforcing-mode image policy remains tracked separately in #2459.
Rationale for this change
Gateway currently cannot use Core with disabled, shadow, or advisory privacy settings. Supporting these modes requires Gateway to honor the deployment mode while Core reports privacy coverage truthfully.
What changes are included in this PR?
coverage.complete=false; enforcing retains request and response privacy enforcement.enforcing=falsepermits incomplete privacy coverage, consistently for send, retry admission, and release. Schema, phase, binding, deadline, block, and withhold checks remain required.OpenAPI, generated models, and Desktop files are unchanged. No new API fields or coverage profiles are introduced. The behavior change is explicit non-enforcing admission for Gateway; existing strict Python SDK and external-executor consumers continue to reject incomplete coverage.
Are there any user-facing changes?
Gateway works with all four configured privacy modes. Disabled skips privacy inspection; shadow and advisory observe requests without blocking and do not inspect responses. These modes do not claim complete privacy protection. Restart Gateway after changing Core's privacy mode to refresh its startup capability discovery. Failed capability discovery does not enable non-enforcing admission.
No database migration is introduced.
How was this change tested?
Head:
b6ad802acec1ffd5e030310ecec2175f9987b044, based on master7fef43d6f(includes the OceanBase scoring test-double fix from #2552).The Rust Gateway sources are unchanged by the mainline synchronization; Python regressions, real Gateway process tests, and make check were rerun on the final head. Remote CI is tracked separately on this PR.
AI usage statement
Implemented and reviewed with OpenAI Codex. Validation scope and environment limitations are recorded above; human review is requested before merge.